package com.cimstech.connect;

import com.cimstech.model.IECResult;
import com.cimstech.model.Value;
import com.cimstech.model.Values;
import com.cimstech.resources.IECResources;
import com.cimstech.websocketservlet.SocketServer;
import monfox.stack.iec61850.api.*;
import monfox.stack.iec61850.api.client.DiscoverOp;
import monfox.stack.iec61850.api.client.IEC61850Client;
import monfox.stack.iec61850.api.client.Report;

import java.util.*;

import javax.ws.rs.ext.Provider;

/**
 * Created by 德予 on 2015/12/10.
 */
public class Connect {
    private static int defaultTimeout = 30000;
    // private static SocketServer socketServer;
    private static Set<SocketServer> socketSet = new HashSet<SocketServer>();

    public static void connect(final String ip, Map<String, IEC61850Client> connPool) throws ACSIServiceErrorException, ModelException {
        {
            if (connPool.containsKey(ip) && connPool.get(ip).isConnected()) {
                return;
            } else {
                String uri = "rfc1006://" + ip + ":102/0x0001/0x0001/0x00000001";
                IEC61850Client client = Commands.getApi().newClient(uri);
                client.setDefaultTimeoutMillis(defaultTimeout);
                // 链接通知
                client.addAssociationListener(new IEC61850Client.AssociationListener() {
                    public void associationUp(IEC61850Client client) {
                        System.out.println("设备：" + ip + " 已连接");
                        for (SocketServer ss : socketSet) {
                            ss.event(ip, "connected");
                        }
                    }

                    public void associationDown(IEC61850Client client) {
                        System.out.println("设备：" + ip + " 已断开");
                        for (SocketServer ss : socketSet) {
                            ss.event(ip, "disconnect");
                        }
                    }
                });
                // 设置模型是否随着报告结构更新，可选
                client.isAutoUpdateOnReport(true);
                // 报告监听
                client.addReportListener(new IEC61850Client.ReportListener() {
                    public void handleReport(IEC61850Client client, Report report) {
                        ArrayList<Value> list = new ArrayList<Value>();
                        for (Report.EntryData data : report.getEntryData()) {
                            try {
                                list.add(Commands.dataValueString(data.getValue(), data.getDataRef()));
                            } catch (ModelValueException e) {
                                e.printStackTrace();
                            }
                        }
                        Values values = new Values();
                        values.setValues(list);
                        values.setIecResponseMessage(IECResult.SUCCESS);
                        int i = 0;
                        for (SocketServer ss : socketSet) {
                            ++i;
                            ss.update(ip, values);
                        }
                        System.out.println("本次报告上送来自设备: " + ip + "\t共推送" + i + "部终端.");
                    }
                });
                System.out.println("开始获取全模型");
                DiscoverOp discover_op = client.newDiscoverOp();
                discover_op.setTimeoutMillis(15000);
                discover_op.isGetDataValues(false);
                DiscoverOp.Response rsp = discover_op.perform();
                if (!(rsp.getException() == null)) {
                    throw rsp.getException();
                } else {
                    System.out.println("插入连接池");
                    synchronized (connPool) {
                        connPool.put(ip, client);
                    }
                }
            }
        }
    }

    public static void setSocketServer(SocketServer s) {
        socketSet.add(s);
    }

    public static void removeSocketServer(SocketServer s) {
        socketSet.remove(s);
        if (socketSet.size() < 1) {
            Iterator<IEC61850Client> iterator = IECResources.getConnPool().values().iterator();
            while (iterator.hasNext()) {
                try {
                    IEC61850Client client = iterator.next();
                    if (client.isConnected()) {
                        client.performRelease();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
